Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces Kafka and Redis into the infrastructure for both development and production environments, migrating the notification system from local application events to Kafka-based messaging. It also integrates an OpenTelemetry collector for refined trace management, adds Redisson for distributed locking, and extends the reservation slot generation window to 90 days. Key feedback focuses on critical data consistency issues where Kafka messages are sent within database transactions, potentially leading to ghost notifications if a rollback occurs. Additionally, the reviewer identified security risks with root-level container execution, hardcoded broker addresses, and error-handling logic in Kafka consumers that could lead to infinite retry loops.
| @Configuration | ||
| public class KafkaConfig { | ||
|
|
||
| private final String bootstrapServers = "localhost:9092"; |
There was a problem hiding this comment.
Kafka 브로커 주소가 localhost:9092로 하드코딩되어 있습니다. 로컬 개발 환경 외의 Docker Compose나 운영 환경에서는 접근이 불가능할 수 있으므로, @Value를 사용하여 외부 설정 파일(application.yml)로부터 주입받도록 수정해야 합니다.
| private final String bootstrapServers = "localhost:9092"; | |
| @Value("${spring.kafka.bootstrap-servers:localhost:9092}") | |
| private String bootstrapServers; |
| restoreInventory(reservation); | ||
| reservation.changeStatus(ReservationStatus.CANCELED); | ||
| eventPublisher.publishEvent(new ReservationCanceledEvent( | ||
| kafkaTemplate.send("notification.reservation.canceled", new ReservationCanceledEvent( |
There was a problem hiding this comment.
kafkaTemplate.send()가 @Transactional 트랜잭션 범위 내에서 호출되고 있습니다. 만약 이후 로직에서 예외가 발생하여 DB 트랜잭션이 롤백되더라도, Kafka 메시지는 이미 발행되어 알림이 발송되는 데이터 불일치 문제가 발생할 수 있습니다.
이 문제를 해결하기 위해:
- 기존처럼
ApplicationEventPublisher를 사용하여 이벤트를 발행하고, @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)를 사용하는 리스너에서 Kafka 메시지를 전송하도록 구현하는 것을 권장합니다.
| @@ -0,0 +1,60 @@ | |||
| package com.catchtable.config; | |||
| kafka: | ||
| image: apache/kafka:3.7.0 | ||
| container_name: catchtable-kafka-prod | ||
| user: "0" # 볼륨 마운트 폴더에 로그를 쓰고 지울 수 있도록 최고 관리자 권한 부여 |
| .orElseThrow(() -> { | ||
| log.error("[Kafka Consumer] 사용자 정보를 찾을 수 없습니다. userId={}", userId); | ||
| return new CustomException(ErrorCode.USER_NOT_FOUND); | ||
| }); |
| @Value("${spring.data.redis.host:localhost}") | ||
| private String host; | ||
|
|
||
| @Value("${spring.data.redis.port:6379}") |
📢 기능 설명
필요시 실행결과 스크린샷 첨부
연결된 issue
연결된 issue를 자동을 닫기 위해 아래 {이슈넘버}를 입력해주세요.
close #{이슈넘버}
✅ 체크리스트